<!DOCTYPE html>
<html lang="zh-CN">
<head>
	<meta charset="UTF-8">
	<meta content="IE=edge" http-equiv="X-UA-Compatible">
	<meta content="initial-scale=1.0, maximum-scale=1.0, user-scalable=no, width=device-width" name="viewport">
	<title>外网映射教程 - UOJ部署指北</title>

	<!-- css -->
	<link href="/css/base.min.css" rel="stylesheet">
	<link href="/css/project.min.css" rel="stylesheet">
	<link href="/css/styles.css" rel="stylesheet">
	<link href="/css/gitalk.css" rel="stylesheet">

</head>
<body class="page-brand">
	
	<header class="header header-transparent header-waterfall ui-header">
		<ul class="nav nav-list pull-left">
			<li>
				<a data-toggle="menu" href="#menu">
					<span class="icon icon-lg">menu</span>
				</a>
			</li>
		</ul>
		<a class="header-logo header-affix-hide margin-left-no margin-right-no" data-offset-top="213" data-spy="affix">外网映射教程</a>
		<span class="header-logo header-affix margin-left-no margin-right-no" data-offset-top="213" data-spy="affix">外网映射教程</span>

		<ul class="nav nav-list pull-right">
			<li>
				<a data-toggle="menu" href="/">
					<span class="avatar avatar-sm"><img alt="logo" src="/img/logo.png"></span>
				</a>
			</li>
		</ul>

	</header>

	<nav aria-hidden="true" class="menu" id="menu" tabindex="-1">
		<div class="menu-scroll">
			<div class="menu-content">
				<a class="menu-logo" href="/">UOJ部署指北</a>
				<ul class="nav">
					<li>
					
						
							
							
								<a class="collapsed waves-attach waves-effect" data-toggle="collapse" href="#入门">入门</a>	
								<ul class="menu-collapse collapse in" id="入门">

								<li>
									<a class="waves-attach" href="/post/安装.html">安装</a>
								</li><li>
									<a class="waves-attach" href="/post/维护.html">维护</a>
								</li><li class="active">
									<a class="waves-attach" href="/post/外网映射教程.html">外网映射教程</a>
								</li><li>
									<a class="waves-attach" href="/post/系统管理.html">系统管理</a>
								</li></ul>
								<a class="collapsed waves-attach waves-effect" data-toggle="collapse" href="#题目">题目</a>	
								<ul class="menu-collapse collapse in" id="题目">

								<li>
									<a class="waves-attach" href="/post/题目管理概述.html">题目管理概述</a>
								</li><li>
									<a class="waves-attach" href="/post/传统题配置.html">传统题配置</a>
								</li><li>
									<a class="waves-attach" href="/post/特殊需求配置.html">特殊需求配置</a>
								</li><li>
									<a class="waves-attach" href="/post/数据检验器.html">数据检验器</a>
								</li><li>
									<a class="waves-attach" href="/post/答案检查器.html">答案检查器</a>
								</li></ul>
								<a class="collapsed waves-attach waves-effect" data-toggle="collapse" href="#开发">开发</a>	
								<ul class="menu-collapse collapse in" id="开发">

								<li>
									<a class="waves-attach" href="/post/SVN简易指北.html">SVN简易指北</a>
								</li><li>
									<a class="waves-attach" href="/post/本地构建镜像.html">本地构建镜像</a>
								</li><li>
									<a class="waves-attach" href="/post/贡献.html">贡献</a>
								</li></ul>
								<a class="collapsed waves-attach waves-effect" data-toggle="collapse" href="#关于">关于</a>	
								<ul class="menu-collapse collapse in" id="关于">

								<li>
									<a class="waves-attach" href="/post/关于.html">关于</a>
								</li></ul>						


					</li>
					
				</ul>
			</div>
		</div>
	</nav>
	<main class="content">
		<div class="content-header ui-content-header">
			<div class="container">
				<tit class="content-heading">外网映射教程</tit>
			</div>
		</div>
		<div class="container">
			<section class="content-inner margin-top-no">
				<div class="row">
					<div class="col-lg-13 col-md-13">
						<div class="card margin-bottom-no">
							<div class="card-main">
								<div class="card-inner page-card-inner">
						<blockquote class="note">
<p>如果您希望让外网访问UOJ，但是服务器没有外网ip，那么您可能需要这篇教程。<br />
本文将引导您将内外的UOJ对外网开放。您可以选择以下方案中的一种。</p>
</blockquote>
<h2>ngrok</h2>
<p>ngrok是一款操作简单的软件，可以把内网的web服务映射到外网。</p>
<p>大部分的ngrok服务是免费的。例如：<a href="https://www.ngrok.cc/">ngrok.cc</a></p>
<blockquote class="note">
<p>ngrok的缺点：</p>
<ul>
<li>速度比较慢</li>
<li>数据并不保密，ngrok服务提供者有能力监听OJ的通讯。</li>
</ul>
</blockquote>
<p>虽然有这几个缺点，ngrok仍然不失为一个好的选择。具体的配置，请参见<a href="https://www.ngrok.cc/">ngrok.cc</a>网站。</p>
<h2>ssh转发</h2>
<p>这个方案需要您有一台VPS，且VPS需要拥有外网ip。<a href="http://pyoj.ml/">PYOJ</a>就是通过这种方式向外网开放的。</p>
<p>首先，您需要在本地机器通过<code>ssh-keygen</code>来生成一个您的密钥：</p>
<div class="codehilite"><pre><span></span>ssh-keygen -t rsa
</pre></div>


<p>一直按<code>enter</code>键，然后您将会在<code>~/.ssh/id_rsa.pub</code>取得您的公钥。         <br />
<img style="max-width:100%" alt="生成公钥" src="https://i.loli.net/2018/10/19/5bc992e392705.png" /></p>
<p>然后登录您的VPS，把上面的公钥扔进<code>~/.ssh/authorized_keys</code>，如下图所示：           <br />
<img style="max-width:100%" alt="VPS" src="https://i.loli.net/2018/10/19/5bc992e3ad19b.png" /></p>
<blockquote class="note">
<p>现在，您在本地机器上使用如下命令，应该可以免密码登录VPS：<br />
<code>bash  
ssh &lt;VPS_user&gt;@&lt;VPS_ip&gt;</code><br />
如果不能登录，您可能对上面过程的理解存在偏差。  </p>
</blockquote>
<p>接下来，在本地机器上安装<code>autossh</code>，它是稳定的ssh连接工具：  </p>
<div class="codehilite"><pre><span></span>sudo apt install autossh
</pre></div>


<p>最后运行下面的指令，将本地的<code>80</code>端口映射到VPS的<code>80</code>端口：  </p>
<div class="codehilite"><pre><span></span>autossh -M <span class="m">5698</span> -NfR &lt;VPS的ip&gt;:80:&lt;本地机器的ip&gt;:80 &lt;VPS用户名&gt;@&lt;VPS的ip&gt;  

<span class="c1"># 例如：</span>
<span class="c1"># autossh -M 5698 -NfR 23.23.23.23:80:127.0.0.1:80 blue@23.23.23.23</span>
<span class="c1"># 5698是监听端口，用于测试ssh连接是否稳定。如果您运行了多个autossh，请保证它们的监听端口不同。</span>
</pre></div>


<p>访问VPS的ip，您应该可以看到UOJ了。</p>
<blockquote class="note">
<p>如果您有域名，请添加一条A记录，指向VPS的ip，然后就能用域名访问了。</p>
</blockquote>
<h2>ssh转发的高级配置</h2>
<p>如果一台VPS需要映射多个网站，那么显然不能都映射到<code>80</code>端口。</p>
<p>在这种情况下，您可以将网站分别映射到<code>10000</code>,<code>10001</code>,<code>10002</code>……然后用nginx来做反代。访问不同的域名将会反代到不同的网站。</p>
<p>VPS上的配置文件（<code>/etc/nginx/conf.d/uoj.conf</code>）大概如下：</p>
<p><a href="http://paste.ubuntu.com/24334214/">http://paste.ubuntu.com/24334214/</a></p>
								<hr>

								<!-- Gitalk 评论框 start -->
								<div id="gitalk-container"></div>
								<!-- Gitalk 评论框 end -->

								</div>
							</div>
						</div>
					</section>
				</div>
			</div>

			
			<hr>
			<center>[CC协议 BY-NC-SA] 署名 - 非商业性使用 - 相同方式共享  @ UOJ部署指北 2018</center>

		</div>


	</main>
	
	<div class="fbtn-container">
		<div class="fbtn-inner">
			<a class="fbtn fbtn-lg fbtn-brand-accent waves-attach waves-circle waves-light" data-toggle="dropdown">
				<span class="fbtn-text fbtn-text-left">Home</span>
				<span class="fbtn-ori icon">apps</span>
				<span class="fbtn-sub icon">close</span>
			</a>
			<div class="fbtn-dropup">
				<a class="fbtn waves-attach waves-circle" href="https://github.com/UniversalOJ/UniversalOJ.github.io/issues" target="_blank">
					<span class="fbtn-text fbtn-text-left">反馈</span><span class="icon">feedback</span>
				</a>
				<a class="fbtn fbtn-green waves-attach waves-circle" href="/" target="_self">
					<span class="fbtn-text fbtn-text-left">返回主页</span><span class="icon">home</span>
				</a>
			</div>
		</div>
	</div>

	

	<!-- js -->
	<script src="/js/jquery.min.js"></script>
	<script src="/js/base.min.js"></script>
    
    <!-- Gitalk JS 代码 start -->
    <script src="/js/gitalk.min.js"></script>
    <script>
    const gitalk = new Gitalk({
      clientID: '0dc093a9aefa1d501df2',
      clientSecret: '3639aabd1bc6b0d9b543be1f13b6bcb2bf7364af',
      repo: 'UniversalOJ.github.io',
	  id: location.pathname,
      owner: 'UniversalOJ',
      admin: ['cebarobot', 'MascoSkray', 'Ruanxingzhi', 'billchenchina'],
      labels: [],
    })
    
    gitalk.render('gitalk-container')
    </script>
    <!-- Gitalk JS 代码 end -->
    
</body>
</html>
